package jiuwu.gqz.audiorecord

import android.media.*
import android.util.Log
import java.io.ByteArrayOutputStream
import java.io.FileOutputStream

class AudioRecordHelper:Thread() {

    private val TAG = "AudioRecordHelper-->"
    val sampleRate = 16000
    val channel = AudioFormat.CHANNEL_IN_MONO
    val channelCount = 1
    val mime = MediaFormat.MIMETYPE_AUDIO_AAC
    val audioFormat = AudioFormat.ENCODING_PCM_16BIT

    var audioRecord: AudioRecord? = null
    var codec: MediaCodec? = null
    var format: MediaFormat? = null
    var minBufSize = 0
    var isRecording = false
    var recordFileHelper = RecordFileHelper()

    init {
        if (audioRecord == null) {
            minBufSize = AudioRecord.getMinBufferSize(
                sampleRate,
                channel,
                audioFormat
            )

            audioRecord = AudioRecord(
                MediaRecorder.AudioSource.MIC,
                sampleRate,
                channel,
                audioFormat,
                minBufSize
            )
        }

        if (codec == null) {
            format = MediaFormat()
            format!!.setString(MediaFormat.KEY_MIME, mime)
            format!!.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channelCount) //声道数（这里是数字）
            format!!.setInteger(MediaFormat.KEY_SAMPLE_RATE, sampleRate) //采样率
            format!!.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE,minBufSize)

            format!!.setInteger(
                MediaFormat.KEY_BIT_RATE, sampleRate * 2 * channelCount
            )//码率
            format!!.setInteger(
                MediaFormat.KEY_AAC_PROFILE,
                MediaCodecInfo.CodecProfileLevel.AACObjectLC
            )

            codec = MediaCodec.createEncoderByType(mime)
            codec!!.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
            codec!!.start()
        }
    }

    /**
     * 给编码出的aac裸流添加adts头字段
     *
     * @param packet    要空出前7个字节，否则会搞乱数据
     * @param packetLen
     */
    fun addADTStoPacket(packet: ByteArray, packetLen: Int) {
        val profile = 1 //0: AAC Main 1:AAC LC (Low Complexity) 2:AAC SSR
        val freqIdx = 0x8 //16000Hz=8 22050=7 32000=5 44100=4
        val chanCfg = 1 //CPE,channel count
        var packLen = packetLen + 7//contains ADTS size
        packet[0] = 0xFF.toByte()
        packet[1] = 0xF1.toByte()
        packet[2] = ((profile shl 6) + (freqIdx shl 2) + (chanCfg shr 2)).toByte()
        packet[3] = (((chanCfg and 3) shl 6) + (packLen shr 11)).toByte()
        packet[4] = ((packLen and 0x7FF) shr 3).toByte()
        packet[5] = (((packLen and 7) shl 5) + 0x1F).toByte()
        packet[6] = 0xFC.toByte()
        Log.i(
            TAG,
            "ADTS: len=" + packetLen + " bits=" + Integer.toHexString(packet[0].toInt() and 0xFF) + " " +
                    Integer.toHexString(packet[1].toInt() and 0xFF) + " " +
                    Integer.toHexString(packet[2].toInt() and 0xFF) + " " +
                    Integer.toHexString(packet[3].toInt() and 0xFF) + " " +
                    Integer.toHexString(packet[4].toInt() and 0xFF) + " " +
                    Integer.toHexString(packet[5].toInt() and 0xFF) + " " +
                    Integer.toHexString(packet[6].toInt() and 0xFF)
        )
    }

    private fun startRecord() {

        var bufferInfo = MediaCodec.BufferInfo()
        audioRecord!!.startRecording()
        val buffer = ByteArray(minBufSize)
        var fos = FileOutputStream(recordFileHelper.createFile())
        var bos = ByteArrayOutputStream(minBufSize)

        while (isRecording) {
            var len = audioRecord!!.read(buffer, 0, minBufSize)

            if (len <= 0) continue

//            fos.write(buffer)//test: write pcm data to file

            var index = codec!!.dequeueInputBuffer(0)
            if (index >= 0) {
                var inputBuffer = codec!!.getInputBuffer(index)
                inputBuffer!!.clear()
                inputBuffer!!.put(buffer, 0, len)
                codec!!.queueInputBuffer(
                    index, 0, len, System.nanoTime() / 1000, 0
                )
            }


            index = codec!!.dequeueOutputBuffer(bufferInfo, 0)
            while (index >= 0 && isRecording) {
                var outputBuffer = codec!!.getOutputBuffer(index)

                var newBuffer = ByteArray(7 + bufferInfo.size)
                outputBuffer!!.position(bufferInfo.offset)
                outputBuffer!!.limit(bufferInfo.offset + bufferInfo.size)
                addADTStoPacket(newBuffer, bufferInfo.size)
                outputBuffer!!.get(newBuffer, 7, bufferInfo.size)

                //write acc data to file
                fos.write(newBuffer)

                codec!!.releaseOutputBuffer(index, false)
                index = codec!!.dequeueOutputBuffer(bufferInfo, 0)
            }
        }

        fos.flush()
        fos.close()
        bos.flush()
        bos.close()
        codec!!.stop()
        codec!!.release()
        audioRecord!!.stop()
        audioRecord!!.release()

    }

    override fun run() {
        startRecord()
    }
}

/*



*/

